/**
 * @class UniStatDataStat uni统计-数据统计调度处理模块
 * @function cron 数据统计定时任务处理函数
 * @function stat 数据统计调度处理函数
 * @function cleanLog 日志清理调度处理函数
 */
const { DateTime } = require('./lib');

const { sleep } = require('../shared');

const {
    BaseMod,
    SessionLog,
    PageLog,
    EventLog,
    ShareLog,
    ErrorLog,
    StatResult,
    ActiveDevices,
    ActiveUsers,
    PageResult,
    EventResult,
    ErrorResult,
    Loyalty,
    RunErrors,
    UserSessionLog,
    uniPay,
    Setting,
} = require('./mod');
class UniStatDataStat {
    /**
     * 数据统计定时任务处理函数
     * @param {Object} context 服务器请求上下文参数
     */
    async cron(context) {
        const baseMod = new BaseMod();
        const dateTime = new DateTime();
        console.log('Cron start time: ', dateTime.getDate('Y-m-d H:i:s'));

        // const setting = new Setting();
        // let settingValue = await setting.getSetting()
        // if (settingValue.mode === "close") {
        // 	// 如果关闭了统计任务，则任务直接结束
        // 	return {
        // 		code: 0,
        // 		msg: 'Task is close',
        // 	}
        // } else if (settingValue.mode === "auto") {
        // 	// 如果开启了节能模式，则判断N天内是否有设备访问记录
        // 	let runKey = await setting.checkAutoRun(settingValue);
        // 	if (!runKey) {
        // 		return {
        // 			code: 0,
        // 			msg: 'Task is auto close',
        // 		}
        // 	}
        // }

        //获取运行参数
        const timeInfo = dateTime.getTimeInfo(null, false);
        const cronConfig = baseMod.getConfig('cron');
        const cronMin = baseMod.getConfig('cronMin');
        const realtimeStat = baseMod.getConfig('realtimeStat');
        // 数据跑批
        let res = null;
        if (cronConfig && cronConfig.length > 0) {
            for (var mi in cronConfig) {
                const currCronConfig = cronConfig[mi];
                const cronType = currCronConfig.type;
                const cronTime = currCronConfig.time.split(' ');
                const cronDimension = currCronConfig.dimension;

                //未开启分钟级定时任务，则设置为小时级定时任务
                if (cronTime.length === 4 && !cronMin) {
                    cronTime.splice(3, 1);
                }

                if (baseMod.debug) {
                    console.log('cronTime', cronTime);
                }
                //精度为分钟级的定时任务
                if (cronTime.length === 4) {
                    if (cronTime[0] !== '*') {
                        //周统计任务
                        if (
                            timeInfo.nWeek == cronTime[0] &&
                            timeInfo.nHour == cronTime[2] &&
                            timeInfo.nMinutes == cronTime[3]
                        ) {
                            let dimension = cronDimension || 'week';
                            console.log(cronType + `--${dimension} run`);
                            res = await this.stat({
                                type: cronType,
                                dimension: cronDimension,
                                config: currCronConfig,
                            });
                        }
                    } else if (cronTime[1] !== '*') {
                        //月统计任务（包含季度统计任务和年统计任务）
                        if (
                            timeInfo.nDay == cronTime[1] &&
                            timeInfo.nHour == cronTime[2] &&
                            timeInfo.nMinutes == cronTime[3]
                        ) {
                            let dimension = cronDimension || 'month';
                            console.log(cronType + `--${dimension} run`);
                            res = await this.stat({
                                type: cronType,
                                dimension: dimension,
                                config: currCronConfig,
                            });
                        }
                    } else if (cronTime[2] !== '*') {
                        //日统计任务
                        if (timeInfo.nHour == cronTime[2] && timeInfo.nMinutes == cronTime[3]) {
                            let dimension = cronDimension || 'day';
                            console.log(cronType + `--${dimension} run`);
                            res = await this.stat({
                                type: cronType,
                                dimension: dimension,
                                config: currCronConfig,
                            });
                        }
                    } else if (cronTime[3] !== '*') {
                        //实时统计任务
                        if (timeInfo.nMinutes == cronTime[3] && realtimeStat) {
                            let dimension = cronDimension || 'hour';
                            console.log(cronType + `--${dimension} run`);
                            res = await this.stat({
                                type: cronType,
                                dimension: dimension,
                                config: currCronConfig,
                            });
                        }
                    }
                }
                //精度为小时级的定时任务
                else if (cronTime.length === 3) {
                    if (cronTime[0] !== '*') {
                        //周统计任务
                        if (timeInfo.nWeek == cronTime[0] && timeInfo.nHour == cronTime[2]) {
                            let dimension = cronDimension || 'week';
                            console.log(cronType + `--${dimension} run`);
                            res = await this.stat({
                                type: cronType,
                                dimension: dimension,
                                config: currCronConfig,
                            });
                        }
                    } else if (cronTime[1] !== '*') {
                        //月统计任务（包含季度统计任务和年统计任务）
                        if (timeInfo.nDay == cronTime[1] && timeInfo.nHour == cronTime[2]) {
                            let dimension = cronDimension || 'month';
                            console.log(cronType + `--${dimension} run`);
                            res = await this.stat({
                                type: cronType,
                                dimension: dimension,
                                config: currCronConfig,
                            });
                        }
                    } else if (cronTime[2] !== '*') {
                        //日统计任务
                        if (timeInfo.nHour == cronTime[2]) {
                            let dimension = cronDimension || 'day';
                            console.log(cronType + `--${dimension} run`);
                            res = await this.stat({
                                type: cronType,
                                dimension: dimension,
                                config: currCronConfig,
                            });
                        }
                    } else {
                        //实时统计任务
                        if (realtimeStat) {
                            let dimension = cronDimension || 'hour';
                            console.log(cronType + `--${dimension} run`);
                            res = await this.stat({
                                type: cronType,
                                dimension: dimension,
                                config: currCronConfig,
                            });
                        }
                    }
                } else {
                    console.error('Cron configuration error');
                }
            }
        }
        console.log('Cron end time: ', dateTime.getDate('Y-m-d H:i:s'));
        return {
            code: 0,
            msg: 'Task have done',
            lastCronResult: res,
        };
    }

    /**
     * 数据统计调度处理函数
     * @param {Object} params 统计参数
     */
    async stat(params) {
        const { type, dimension, date, reset, config } = params;
        let res = {
            code: 0,
            msg: 'success',
        };

        try {
            switch (type) {
                // 基础统计
                case 'stat': {
                    const resultStat = new StatResult();
                    res = await resultStat.stat(dimension, date, reset);
                    break;
                }
                // 活跃设备统计归集
                case 'active-device': {
                    const activeDevices = new ActiveDevices();
                    res = await activeDevices.stat(date, reset);
                    break;
                }
                // 活跃用户统计归集
                case 'active-user': {
                    const activeUsers = new ActiveUsers();
                    res = await activeUsers.stat(date, reset);
                    break;
                }
                // 设备留存统计
                case 'retention-device': {
                    const retentionStat = new StatResult();
                    res = await retentionStat.retentionStat(dimension, date);
                    break;
                }
                // 用户留存统计
                case 'retention-user': {
                    const retentionStat = new StatResult();
                    res = await retentionStat.retentionStat(dimension, date, 'user');
                    break;
                }
                // 页面统计
                case 'page': {
                    const pageStat = new PageResult();
                    res = await pageStat.stat(dimension, date, reset);
                    break;
                }
                // 事件统计
                case 'event': {
                    const eventStat = new EventResult();
                    res = await eventStat.stat(dimension, date, reset);
                    break;
                }
                // 错误统计
                case 'error': {
                    const errorStat = new ErrorResult();
                    res = await errorStat.stat(dimension, date, reset);
                    break;
                }
                // 设备忠诚度统计
                case 'loyalty': {
                    const loyaltyStat = new Loyalty();
                    res = await loyaltyStat.stat(dimension, date, reset);
                    break;
                }
                // 日志清理
                case 'clean': {
                    res = await this.cleanLog();
                }
                // 支付统计
                case 'pay-result': {
                    const paymentResult = new uniPay.PayResult();
                    res = await paymentResult.stat(dimension, date, reset, config);
                    break;
                }
            }
        } catch (e) {
            const maxTryTimes = 2;
            if (!this.tryTimes) {
                this.tryTimes = 1;
            } else {
                this.tryTimes++;
            }

            //报错则重新尝试2次, 解决部分云服务器偶现连接超时问题
            if (this.tryTimes <= maxTryTimes) {
                //休眠1秒后重新调用
                sleep(1000);
                params.reset = true;
                res = await this.stat(params);
            } else {
                // 2次尝试失败后记录错误
                console.error('server error: ' + e);
                const runError = new RunErrors();
                runError.create({
                    mod: 'stat',
                    params: params,
                    error: e,
                    create_time: new DateTime().getTime(),
                });

                res = {
                    code: 500,
                    msg: 'server error' + e,
                };
            }
        }
        return res;
    }

    /**
     * 日志清理调度处理函数
     */
    async cleanLog() {
        const baseMod = new BaseMod();
        const cleanLog = baseMod.getConfig('cleanLog');
        if (!cleanLog || !cleanLog.open) {
            return {
                code: 100,
                msg: 'The log cleanup service has not been turned on',
            };
        }

        const res = {
            code: 0,
            msg: 'success',
            data: {},
        };

        // 会话日志
        if (cleanLog.reserveDays.sessionLog > 0) {
            const sessionLog = new SessionLog();
            res.data.sessionLog = await sessionLog.clean(cleanLog.reserveDays.sessionLog);
        }

        // 用户会话日志
        if (cleanLog.reserveDays.userSessionLog > 0) {
            const userSessionLog = new UserSessionLog();
            res.data.userSessionLog = await userSessionLog.clean(cleanLog.reserveDays.userSessionLog);
        }

        // 页面日志
        if (cleanLog.reserveDays.pageLog > 0) {
            const pageLog = new PageLog();
            res.data.pageLog = await pageLog.clean(cleanLog.reserveDays.pageLog);
        }

        // 事件日志
        if (cleanLog.reserveDays.eventLog > 0) {
            const eventLog = new EventLog();
            res.data.eventLog = await eventLog.clean(cleanLog.reserveDays.eventLog);
        }

        // 分享日志
        if (cleanLog.reserveDays.shareLog > 0) {
            const shareLog = new ShareLog();
            res.data.shareLog = await shareLog.clean(cleanLog.reserveDays.shareLog);
        }

        // 错误日志
        if (cleanLog.reserveDays.errorLog > 0) {
            const errorLog = new ErrorLog();
            res.data.errorLog = await errorLog.clean(cleanLog.reserveDays.errorLog);
        }

        // 活跃设备日志
        const activeDevicesLog = new ActiveDevices();
        res.data.activeDevicesLog = await activeDevicesLog.clean();

        // 活跃用户日志
        const activeUsersLog = new ActiveUsers();
        res.data.activeUsersLog = await activeUsersLog.clean();

        // 实时统计日志
        const resultHourLog = new StatResult();
        res.data.resultHourLog = await resultHourLog.cleanHourLog();

        //原生应用崩溃日志
        const appCrashLogs = new AppCrashLogs();
        res.data.appCrashLogs = await appCrashLogs.clean();

        return res;
    }
}

module.exports = UniStatDataStat;
